Skip to content

fix: 포트폴리오 개인/외주 구분을 선택 입력으로 변경 - #177

Merged
sangwon02 merged 3 commits into
mainfrom
fix/176-portfolio-kind-optional
Aug 12, 2026
Merged

fix: 포트폴리오 개인/외주 구분을 선택 입력으로 변경#177
sangwon02 merged 3 commits into
mainfrom
fix/176-portfolio-kind-optional

Conversation

@sangwon02

@sangwon02 sangwon02 commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

🔗 관련 이슈 (Related Issue)

Closes #176

📝 작업 내용

포트폴리오의 개인/외주 구분(kind)을 필수에서 선택 입력으로 바꿨습니다. 목록 조회나 필터에 쓰이지 않는 값이라 등록 단계에서 선택을 강요할 이유가 없었습니다.

주요 변경 사항

  • PortfolioCreateRequest.kind@NotNull 제거, UserPortfolio.kind 를 nullable 로 변경
  • 구분을 고르지 않고 의뢰자만 입력하는 것도 허용
  • 프로젝트 완료 전환의 kind 검증과 PROJECT_COMPLETION_INFO_REQUIRED 제거
  • V022__portfolio_kind_nullable.sql 추가

상세 내용

1. 의뢰자 저장 조건을 뒤집었습니다

// 변경 전 : kind == EXTERNAL ? clientName : null
// 변경 후 : kind == PERSONAL  ? null : clientName

기존 조건이면 kind 를 비웠을 때 의뢰자까지 함께 사라집니다. 개인 작업으로 명시한 경우에만 비우도록 바꿔, 구분 없이 의뢰자만 입력하는 것을 허용했습니다.

2. 프로젝트 완료 검증이 죽은 코드가 되어 제거했습니다

이 검증은 포트폴리오의 kind 가 NOT NULL 이라 자동 생성이 실패하는 것을 막으려고 넣은 것입니다. nullable 이 되면서 실패 가능성이 사라졌고, 남는 조건인 title 은 프로젝트 생성·수정 요청 모두 @NotBlank 라 비어질 수 없어 발동하지 않습니다.

ProjectController@ApiErrorCodes 에서도 PROJECT_COMPLETION400 을 함께 뺐습니다. ErrorCodeRegistry 는 등록되지 않은 코드를 만나면 예외를 던지므로 한쪽만 고치면 문서 생성이 실패합니다.

3. 마이그레이션에서 ENUM 을 VARCHAR 로 함께 전환했습니다

운영 DB 는 ddl-auto=update 로 생성된 구간이 있어 이 컬럼이 MySQL ENUM 일 수 있습니다. V009(activity_log.type), V020(notification.type) 과 같은 처리를 했습니다. PERSONAL / EXTERNAL 값은 문자열로 그대로 보존됩니다.

ALTER TABLE user_portfolio MODIFY COLUMN kind VARCHAR(255) NULL;

제약 완화라 기존 코드가 동작 중인 DB 에 먼저 적용해도 안전합니다.

4. 테스트

기존 검증 테스트를 삭제하지 않고 새 동작 검증으로 교체했습니다.

변경 전 : 개인/외주 구분이 없으면 완료로 바꿀 수 없다
변경 후 : 개인/외주 구분이 없는 프로젝트도 완료되고 포트폴리오는 구분 없이 생성된다

전체 테스트 스위트 통과를 확인했습니다.

5. 프론트엔드 영향

API 변경
POST /api/v1/users/me/portfolios kind 가 필수에서 선택으로 변경
GET /api/v1/users/me/portfolios/{portfolioId} kindnull 로 내려올 수 있음
PATCH /api/v1/projects/{projectId} PROJECT_COMPLETION400 제거

등록 폼에서 개인/외주 선택을 필수 해제하고, 이력 카드에 구분을 표시한다면 값이 없는 경우 처리가 필요합니다.

✅ PR 체크리스트

  • PR 제목은 커밋 컨벤션을 따랐습니다.
  • 관련 이슈를 연결했습니다.
  • 변경 사항에 대한 테스트를 진행했습니다.

Summary by CodeRabbit

  • 변경 사항
    • 프로젝트 완료 시 제목과 개인/외주 구분 없이 완료할 수 있도록 변경했습니다.
    • 포트폴리오 생성 시 개인/외주 구분 입력을 선택 사항으로 변경했습니다.
    • 개인 포트폴리오에서는 의뢰자 정보가 저장되지 않습니다.
    • 관련 API 안내와 오류 코드 설명을 업데이트했습니다.
    • 구분 정보가 없는 포트폴리오도 정상적으로 생성·저장됩니다.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3b4fbcd4-307c-4f84-8b0e-8bed70ebcaf1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

프로젝트 완료 시 kind 누락을 허용합니다. 포트폴리오 생성 요청과 데이터베이스 컬럼도 kind 없이 처리하도록 변경합니다. PERSONAL 유형의 의뢰자명 처리 규칙과 관련 API 문서 및 테스트를 갱신합니다.

Changes

포트폴리오 kind 선택 입력 전환

Layer / File(s) Summary
포트폴리오 입력 및 저장 계약 변경
src/main/java/com/slatto/domain/user/dto/PortfolioCreateRequest.java, src/main/java/com/slatto/domain/user/controller/PortfolioController.java, src/main/java/com/slatto/domain/user/service/PortfolioService.java, src/main/java/com/slatto/domain/user/entity/UserPortfolio.java, src/main/resources/db/migration/V022__portfolio_kind_nullable.sql
kind의 필수 검증을 제거합니다. user_portfolio.kindNULL을 허용합니다. PERSONAL일 때만 의뢰자명을 제거합니다. API 설명과 데이터베이스 마이그레이션을 갱신합니다.
프로젝트 완료 검증 제거 및 테스트 갱신
src/main/java/com/slatto/domain/project/exception/ProjectErrorCode.java, src/main/java/com/slatto/domain/project/controller/ProjectController.java, src/main/java/com/slatto/domain/project/service/ProjectService.java, src/test/java/com/slatto/domain/project/service/ProjectCompletionPortfolioTest.java
프로젝트 완료 시 title·kind 검증과 PROJECT_COMPLETION_INFO_REQUIRED 오류 코드를 제거합니다. kind가 없는 프로젝트도 완료되고 null kind 포트폴리오가 생성되도록 테스트를 변경합니다.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested labels: fix

Suggested reviewers: chazy-d

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant ProjectController
  participant ProjectService
  participant PortfolioService
  Client->>ProjectController: 프로젝트 완료 요청
  ProjectController->>ProjectService: 완료 처리 호출
  ProjectService->>PortfolioService: 프로젝트 정보로 포트폴리오 생성
  PortfolioService-->>ProjectService: kind가 null인 포트폴리오 반환
  ProjectService-->>ProjectController: 완료 결과 반환
  ProjectController-->>Client: 성공 응답
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 포트폴리오의 개인/외주 구분을 선택 입력으로 변경하는 핵심 변경 사항을 명확하게 요약합니다.
Description check ✅ Passed 관련 이슈, 작업 내용, 주요 변경 사항, 테스트 결과와 체크리스트가 템플릿에 맞게 작성되었습니다.
Linked Issues check ✅ Passed 코드 변경이 #176의 선택 입력, nullable 마이그레이션, clientName 처리, 완료 검증 제거와 문서 동기화 요구를 충족합니다.
Out of Scope Changes check ✅ Passed 변경된 컨트롤러, 서비스, 엔티티, 마이그레이션과 테스트가 모두 #176의 범위와 직접 관련됩니다.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/com/slatto/domain/project/service/ProjectService.java (1)

220-232: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

kind만 선택 입력으로 바꾸고 title 검증은 유지해야 합니다.

Line 223 부근에서 제목과 kind를 함께 검사하던 완료 전 검증을 모두 제거했습니다. PR objective는 kind만 선택 입력으로 변경합니다. PortfolioService.createProjectPortfoliosproject.getTitle()UserPortfolio.create로 전달하고, UserPortfolio.titlenullable = false입니다. 제목이 null인 프로젝트가 완료되면 포트폴리오 저장이 DB 제약 위반으로 실패합니다. 빈 문자열이면 기존 @NotBlank 계약도 우회합니다. kind 조건만 제거하고 제목 조건은 별도 오류 코드로 유지하세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/slatto/domain/project/service/ProjectService.java` around
lines 220 - 232, Restore title validation in the completion flow around
completeProject while keeping kind optional by removing only the kind check.
Reject null or blank project titles with the existing dedicated title-validation
error code before markCompleted or portfolio creation, preserving the current
behavior for valid titles.
🧹 Nitpick comments (1)
src/test/java/com/slatto/domain/project/service/ProjectCompletionPortfolioTest.java (1)

185-210: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

kind == null일 때 clientName 보존을 검증하세요.

현재 테스트는 kind가 없는 완료만 검증하고 clientName은 입력하지 않습니다. 따라서 resolveClientName(null, clientName)이 실제 값으로 실행되지 않으며, null kind에서 clientName을 버리는 회귀도 통과합니다. 완료 요청에 clientName을 추가하고 저장된 포트폴리오의 값을 검증하세요.

테스트 보강 예시
     private ProjectUpdateRequest completeRequestWithoutKind() {
         return request("""
-            {"title":"종류 없는 프로젝트","type":"FILM_DRAMA","lengthType":"SHORT_FORM","description":"설명",
+            {"title":"종류 없는 프로젝트","type":"FILM_DRAMA","lengthType":"SHORT_FORM","description":"설명","clientName":"클라이언트 Y",
              "endDate":"%s","status":"COMPLETED"}
             """.formatted(LocalDate.now().plusDays(10)));
     }

                 assertThat(portfolio.getTitle()).isEqualTo("종류 없는 프로젝트");
                 assertThat(portfolio.getKind()).isNull();
+                assertThat(portfolio.getClientName()).isEqualTo("클라이언트 Y");
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/slatto/domain/project/service/ProjectCompletionPortfolioTest.java`
around lines 185 - 210, Update
completeProject_withoutKind_createsPortfolioWithNullKind and
completeRequestWithoutKind() to supply a concrete clientName while kind remains
null, then assert the saved portfolio preserves that clientName alongside the
existing null-kind assertion. Ensure the test exercises resolveClientName(null,
clientName) through the completion flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/main/java/com/slatto/domain/project/service/ProjectService.java`:
- Around line 220-232: Restore title validation in the completion flow around
completeProject while keeping kind optional by removing only the kind check.
Reject null or blank project titles with the existing dedicated title-validation
error code before markCompleted or portfolio creation, preserving the current
behavior for valid titles.

---

Nitpick comments:
In
`@src/test/java/com/slatto/domain/project/service/ProjectCompletionPortfolioTest.java`:
- Around line 185-210: Update
completeProject_withoutKind_createsPortfolioWithNullKind and
completeRequestWithoutKind() to supply a concrete clientName while kind remains
null, then assert the saved portfolio preserves that clientName alongside the
existing null-kind assertion. Ensure the test exercises resolveClientName(null,
clientName) through the completion flow.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: cd830b53-27d4-4459-8e0e-e67e36bd28d6

📥 Commits

Reviewing files that changed from the base of the PR and between 85a8799 and 750d9dd.

📒 Files selected for processing (9)
  • src/main/java/com/slatto/domain/project/controller/ProjectController.java
  • src/main/java/com/slatto/domain/project/exception/ProjectErrorCode.java
  • src/main/java/com/slatto/domain/project/service/ProjectService.java
  • src/main/java/com/slatto/domain/user/controller/PortfolioController.java
  • src/main/java/com/slatto/domain/user/dto/PortfolioCreateRequest.java
  • src/main/java/com/slatto/domain/user/entity/UserPortfolio.java
  • src/main/java/com/slatto/domain/user/service/PortfolioService.java
  • src/main/resources/db/migration/V022__portfolio_kind_nullable.sql
  • src/test/java/com/slatto/domain/project/service/ProjectCompletionPortfolioTest.java

@sangwon02
sangwon02 merged commit 52e531a into main Aug 12, 2026
2 checks passed
@sangwon02
sangwon02 deleted the fix/176-portfolio-kind-optional branch August 12, 2026 14:44
@guingguing guingguing added the fix 버그 수정 label Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix 버그 수정

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FIX: 포트폴리오 개인/외주 구분을 선택 입력으로 변경

5 participants